package com.lhj.springboot.web.component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collection;

/**
 * @Description
 * @Author lhj
 * @Date 2024/6/15 22:40
 */

public class YamlHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
    
    private ObjectMapper mapper;
    
    public YamlHttpMessageConverter() {
        super(new MediaType("text", "yaml", Charset.forName("UTF-8")));
        YAMLFactory factory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
        this.mapper = new ObjectMapper(factory);
    }
    
    @Override
    protected boolean supports(Class<?> clazz) {
        return true;
    }
    
    /**
     * @Description @RequestBody 使用 @RequestBody 接收请求体中参数的转换
     * @param clazz the type of object to return
     * @param inputMessage the HTTP input message to read from
     * @return
     * @throws IOException
     * @throws HttpMessageNotReadableException
     */
    @Override
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    /**
     * @Description @ResponseBody 返回Yaml
     * @param returnValue the object to write to the output message
     * @param outputMessage the HTTP output message to write to
     * @throws IOException
     * @throws HttpMessageNotWritableException
     */
    @Override
    protected void writeInternal(Object returnValue, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        try (OutputStream os = outputMessage.getBody()){
            mapper.writeValue(os, returnValue);
        }
    }



    private static boolean checkReturnType(Class<?> clazz) {
        //检查是否为基本数据类型 (不包含void)
        if (clazz.isPrimitive()) {
            return false;
        }
        // 判断是否为包装类
        if (clazz.equals(Byte.class) ||
                clazz.equals(Short.class) ||
                clazz.equals(Integer.class) ||
                clazz.equals(Long.class) ||
                clazz.equals(Float.class) ||
                clazz.equals(Double.class) ||
                clazz.equals(Boolean.class) ||
                clazz.equals(Character.class)) {
            return false;
        }
        //判断是否为数组
        if (clazz.isArray()) {
            return false;
        }
        // 检查是否为集合框架中的类型
        if (Collection.class.isAssignableFrom(clazz)) {
            return false;
        }
        // 简单检查是否有至少一个字段，作为实体类的一个基本条件
        return Arrays.stream(clazz.getDeclaredFields()).findFirst().isPresent();
    }

}

